import { DeleteOutlined, EditOutlined } from '@ant-design/icons'
import { useObservable } from '@gnlab/utils/env-react/rx'
import { Tag, Tabs, Modal, Button, message } from 'antd'
import { ReactComponent as AppCenterIcon } from '@/desktop/assets/app-center.svg'
import { Empty } from '@/desktop/components'
import BeautyMenu from '@/desktop/components/BeautyMenu'
import { flexCenter, ellipsis, flexCol } from '@/desktop/styles'
import { SiderItem } from '@/desktop/views/app'
import { panelSubject, CoverPanel, siderOpenStyle } from '@/desktop/views/app/cover-panel'
import { useStreams } from '@/lib/utils'
import useUIMemory from '@/logics/memory'
import services from '@/services'
import type { ThirdApp } from '@/services/features/third-apps'
import { EditApp } from './edit'
import {
  useCategories,
  useSortedCategories,
  useRecordOpen,
  type AppCategoryForSCRM,
  type AppCategory,
  type AppMenu,
} from './logics'

export function AppCenter({ collapsed }: { collapsed: boolean }) {
  const { formattedCategories, allMenus, isAdmin } = useCategories()
  const { recordOpen } = useRecordOpen()

  // 向 SCRM 发送应用列表
  useEffect(() => {
    const toScrm: AppCategoryForSCRM[] = formattedCategories
      .filter(c => c.id !== 'all')
      .map(c => {
        const menus = c.menus
          .map(menu => ({ id: menu.id, name: menu.name }))
          .sort((a, b) => a.name.length - b.name.length)
        if (c.id === 'third') menus.unshift({ id: 'add-app', name: '添加应用' })
        return { ...c, menus }
      })
    services.scrm.send('menus', toScrm)
  }, [formattedCategories])

  // 控制 App 的开启/关闭
  const [openingModalApp, setOpeningModalApp] = useState<string | null>(null)
  const closeModalApp = useCallback(() => setOpeningModalApp(null), [])
  const openApp = useCallback(
    (id: string) => {
      const menu = allMenus.find(v => v.id === id)
      if (!menu) return

      recordOpen(id)
      if ('panel' in menu) {
        panelSubject.next(menu.component)
      } else {
        setOpeningModalApp(id)
      }
    },
    [recordOpen, allMenus],
  )
  useObservable(
    services.scrm.message<string>('open-menu'),
    message => {
      if (message.data === 'add-app') setThirdEditing(true)
      else openApp(message.data)
    },
    [openApp],
  )

  // 处理自建应用的编辑
  const [thirdEditing, setThirdEditing] = useState<ThirdApp | true | null>(null)
  const removeThird = useCallback((app: ThirdApp) => {
    void Modal.confirm({
      title: '确定要删除此应用吗？',
      async onOk() {
        const res = await services.features.thirdApps.remove(app.id)
        if (res === true) {
          void message.success('应用已删除')
        } else {
          void message.warning(`应用删除失败：${res}`)
        }
      },
    })
  }, [])
  useObservable(
    services.scrm.message<{ id: string }>('edit-app'),
    message => {
      const thirdApp = allMenus.find(v => v.id === message.data.id)?.thirdApp
      if (thirdApp) setThirdEditing(thirdApp)
    },
    [allMenus],
  )
  useObservable(
    services.scrm.message<{ id: string }>('remove-app'),
    message => {
      const thirdApp = allMenus.find(v => v.id === message.data.id)?.thirdApp
      if (thirdApp) removeThird(thirdApp)
    },
    [allMenus],
  )

  const WrappedAppCenterPanel = useCallback(() => {
    const props = {
      formattedCategories,
      allMenus,
      isAdmin,
      openApp,
      removeThird,
      setThirdEditing,
    }
    return <AppCenterPanel {...props} />
  }, [formattedCategories, allMenus, isAdmin, openApp])

  return <>
    {allMenus.map(menu => {
      if ('panel' in menu) return null
      return <menu.component
        key={menu.id}
        open={openingModalApp === menu.id}
        onClose={closeModalApp}
      />
    })}

    <EditApp editing={thirdEditing} onFinish={() => setThirdEditing(null)} />

    <AppCenterToggle collapsed={collapsed} Panel={WrappedAppCenterPanel} />
  </>
}

function AppCenterToggle({
  collapsed,
  Panel,
}: {
  collapsed: boolean
  Panel: () => React.ReactNode
}) {
  const [openingPanel] = useStreams(panelSubject)
  const opening = openingPanel === Panel

  if (services.scrm.inSCRM) return null
  return <SiderItem
    css={opening && siderOpenStyle}
    className={collapsed ? 'collapsed' : ''}
    collapsed={collapsed}
    icon={<AppCenterIcon />}
    title="应用中心"
    tooltip="打开应用中心"
    onClick={() => panelSubject.next(opening ? null : Panel)}
  />
}

function AppCenterPanel({
  formattedCategories,
  allMenus,
  isAdmin,
  setThirdEditing,
  openApp,
  removeThird,
}: {
  formattedCategories: AppCategory[]
  allMenus: AppMenu[]
  isAdmin: boolean
  openApp: (id: string) => void
  removeThird: (app: ThirdApp) => void
  setThirdEditing: (editing: true | ThirdApp | null) => void
}) {
  const [tab, setTab] = useUIMemory('app-center-tab', 'all')
  const categories = useSortedCategories(formattedCategories, allMenus)

  return <>
    <CoverPanel
      title="应用中心"
      extra={
        isAdmin ? (
          <Button css={styles.headerButton} onClick={() => setThirdEditing(true)}>
            创建应用
          </Button>
        ) : null
      }
    >
      <Tabs
        css={styles.tabs}
        activeKey={tab}
        onChange={setTab}
        destroyInactiveTabPane
        items={categories.map(category => {
          return {
            label: category.name,
            key: category.id,
            children: <Menus
              category={category}
              openApp={openApp}
              editThird={setThirdEditing}
              removeThird={removeThird}
              isAdmin={isAdmin}
            />,
          }
        })}
      />
    </CoverPanel>
  </>
}

function Menus({
  category,
  openApp,
  editThird,
  removeThird,
  isAdmin,
}: {
  category: AppCategory
  openApp: (id: string) => void
  editThird: (app: ThirdApp) => void
  removeThird: (app: ThirdApp) => void
  isAdmin: boolean
}) {
  function getThirdMenu(menu: AppMenu) {
    const app = menu.thirdApp
    return app && isAdmin ? (
      <BeautyMenu
        items={[
          { icon: <EditOutlined />, title: '编辑', onClick: () => editThird(app) },
          { icon: <DeleteOutlined />, title: '删除', onClick: () => removeThird(app) },
        ]}
      />
    ) : null
  }

  return <div css={styles.menus}>
    {category.menus.map(menu => <div
      key={menu.id}
      css={styles.menu}
      onClick={() => openApp(menu.id)}
    >
      <span className="icon">{menu.icon}</span>
      <span className="name">{menu.name}</span>
      {menu.beta === true ? <Tag css={styles.beta}>内测</Tag> : null}
      {getThirdMenu(menu)}
    </div>)}
    {category.id === 'third' && !category.menus.length ? (
      <Empty description="尚未添加应用" css={styles.empty} />
    ) : null}
  </div>
}

const styles = {
  headerButton: css`
    padding: 7px 26px;
    height: 38px;
  `,
  tabs: css`
    ${flexCol};
    flex: 1;
    overflow: hidden;
    .ant-tabs-nav {
      margin-bottom: 0;
    }
    .ant-tabs-tab {
      color: rgba(0, 0, 0, 0.65);
      font-size: 16px;
    }
    .ant-tabs-content-holder {
      padding-top: 40px;
      flex: 1;
      overflow-y: auto;
    }
  `,
  menus: css`
    display: flex;
    flex-wrap: wrap;
    column-gap: 30px;
    row-gap: 30px;
  `,
  menu: css`
    align-items: center;
    background-color: #f8f8fa;
    border-radius: 8px;
    cursor: pointer;
    display: flex;
    padding: 14px;
    transition: background-color 0.2s;
    width: 228px;
    &:hover {
      background-color: #f3f3f5;
    }

    .icon {
      ${flexCenter};
      border-radius: 8px;
      font-size: 42px;
      height: 42px;
      margin-right: 14px;
      overflow: hidden;
      width: 42px;
      flex-shrink: 0;
      img {
        max-height: 100%;
        max-width: 100%;
      }
    }

    .name {
      ${ellipsis};
      color: rgba(0, 0, 0, 0.65);
      flex: 1;
      font-size: 16px;
    }
  `,
  beta: css`
    background-color: #fff;
    color: rgba(0, 0, 0, 0.65);
    margin: 1px 0 0 2px;
    transform-origin: right;
    transform: scale(0.9);
  `,
  empty: css`
    width: 100%;
  `,
}
